package com.justech.mes.utils;

import com.justech.mes.v2.model.dto.ShortInterval;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;

import static com.justech.mes.utils.DateUtil.DateConstant.addDay;

/**
 * excel工具类
 *
 * @author jacky
 */
public class DateUtil {
    private static final Logger log = LoggerFactory.getLogger("DateUtil");

    public static Date now() {
        return DateUtil.DateConstant.currentDate();
    }

    public static String splitTime(Date date) {
        return dateToString(date).split(" ")[1];
    }

    /**
     * 将时间区间按天拆分成多个时间区间
     *
     * @param startStamp
     * @param endStamp
     * @return
     */
    public static List<ShortInterval> segmentationByDay(Long startStamp, Long endStamp) {

        return null;
    }

    public static Long getShortStamp(Date date) {
        if (ObjectUtil.isNull(date)) {
            throw new NumberFormatException("Date must not be empty");
        }
        return date.getTime() % (1000 * 60 * 60 * 24);
    }

    public static Long getCurrentStamp() {
        return getShortStamp(now());
    }

    /**
     * 将时间段按天分割成多个时间段
     *
     * @param startDate
     * @param endDate
     * @return
     */
    public static List<ShortInterval> segmentationByDay(Date startDate, Date endDate) {
        return TimeCutting.cutSlotToPoint(startDate, endDate);
    }

    /**
     * 作者：一勺菠萝丶
     * 来源：CSDN
     * 原文：https://blog.csdn.net/weixin_39973810/article/details/81982789
     * 版权声明：本文为博主原创文章，转载请附上博文链接！
     *
     * @param date
     * @return
     */
    public static Date getDayMorning(Date date) {
        java.util.Calendar cal = java.util.Calendar.getInstance();
        cal.setTime(date);
        cal.set(cal.get(java.util.Calendar.YEAR), cal.get(java.util.Calendar.MONTH), cal.get(java.util.Calendar.DAY_OF_MONTH), 0, 0, 0);
        Date beginOfDate = cal.getTime();
        return beginOfDate;
    }

    public static boolean isSameDate(Date date1, Date date2) {
        MesAssert.isTrue(ObjectUtil.isNull(date1) || ObjectUtil.isNull(date2), "Neither date is empty for comparison");
        return dateToShortString(date1).equals(dateToShortString(date2));
    }

    public static String getFirstDayOfMonth(String today) {
        Date date = stringToDate(today);
        java.util.Calendar calendar = java.util.Calendar.getInstance();
        calendar.setTime(date);

        return getFisrtDayOfMonth(calendar.get(java.util.Calendar.YEAR), calendar.get(java.util.Calendar.MONTH) + 1);
    }


    @SuppressWarnings("all")
    public static String getFisrtDayOfMonth(int year, int month) {
        java.util.Calendar cal = java.util.Calendar.getInstance();
        cal.set(java.util.Calendar.YEAR, year);
        cal.set(java.util.Calendar.MONTH, month - 1);
        int firstDay = cal.getActualMinimum(java.util.Calendar.DAY_OF_MONTH);
        cal.set(java.util.Calendar.DAY_OF_MONTH, firstDay);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
        String firstDayOfMonth = sdf.format(cal.getTime());

        return firstDayOfMonth;
    }

    public static Date aroundToday(int range) {
        return addDay(now(), range);
    }

    public static String aroundTodayString(int range) {
        return dateToShortString(addDay(now(), range));
    }


    public static class Current {
        public static String year() {
            return null;
        }
    }

    public static Date dateParse(String date, String param) {
        SimpleDateFormat sdf = new SimpleDateFormat(param);
        Date a = null;
        try {
            a = sdf.parse(date);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return a;
    }

    /**
     * 格式转换  2010/12/12 00:00:00-----》2010-12-12 00:00:00
     *
     * @param date
     * @return
     */
    public static String dateParse2(String date) {
        SimpleDateFormat sdfx = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
        SimpleDateFormat sdfh = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String nowTime2 = "";
        try {
            nowTime2 = sdfh.format(sdfx.parse("2010/12/12 00:00:00"));
        } catch (Exception e) {
            e.printStackTrace();
        }
        return nowTime2;
    }

    /**
     * 格式转换  2010-12-12 00:00:00-----》2010-12-12
     *
     * @param date
     * @return
     */
    public static String datetimeToDate(String date) {
        String[] nowTime2 = date.split(" ");

        return nowTime2[0];
    }

    /**
     * 自定义时间格式转换
     *
     * @param date
     * @param partten
     * @return
     */
    public static Date parse(Date date, String partten) {
        SimpleDateFormat dateFormat = new SimpleDateFormat(partten);
        String format = dateFormat.format(date);
        try {
            return dateFormat.parse(format);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static Date parse(String date) {
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:Ss");
        try {
            return dateFormat.parse(date);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 获取今年的第一天
     *
     * @return
     */
    public static Date getCurrYearFirst() {
        java.util.Calendar currCal = java.util.Calendar.getInstance();
        int currentYear = currCal.get(java.util.Calendar.YEAR);
        return getYearFirst(currentYear);
    }

    /**
     * 获取某一年的第一天
     *
     * @param year
     * @return
     */
    public static Date getYearFirst(int year) {
        java.util.Calendar calendar = java.util.Calendar.getInstance();
        calendar.clear();
        calendar.set(java.util.Calendar.YEAR, year);
        Date currYearFirst = calendar.getTime();
        return currYearFirst;
    }

    /**
     * 获取某天的最初时间点
     *
     * @param date
     * @return
     */
    public static Date getDayFirst(Date date) {
        LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(date.getTime()), ZoneId.systemDefault());
        LocalDateTime startOfDay = localDateTime.with(LocalTime.MIN);
        return Date.from(startOfDay.atZone(ZoneId.systemDefault()).toInstant());
    }

    /**
     * 获取某天最晚的时间点
     *
     * @param date
     * @return
     */
    public static Date getDayLast(Date date) {
        LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(date.getTime()), ZoneId.systemDefault());
        ;
        LocalDateTime endOfDay = localDateTime.with(LocalTime.MAX);
        return Date.from(endOfDay.atZone(ZoneId.systemDefault()).toInstant());
    }

    public static void main(String[] args) {
        Long bantch_start = 1000 * 60 * 60 * 8L;
        Long bantch_end = 1000 * 60 * 60 * 12L;
        Long day = 1000 * 60 * 60 * 24L;
        System.out.println(DateUtil.countDateIntersection((1566528589000L - 1566489600000L), (1566528798000L - 1566489600000L), bantch_start, bantch_end));
    }

    /**
     * 判断目标时间是否在开始和结束之间
     *
     * @param start
     * @param end
     * @param source
     * @return
     */
    public static boolean between(Date start, Date end, Date source) {
        return source.getTime() >= start.getTime() && source.getTime() <= end.getTime();
    }

    /**
     * 将长时间格式时间转换为字符串 yyyy-MM-dd
     *
     * @param dateDate
     * @return
     */
    public static String dateToShortDate(java.util.Date dateDate) {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        String dateString = formatter.format(dateDate);
        return dateString;
    }

    /**
     * 将长时间格式时间转换为字符串 yyyy-MM-dd HH:mm:ss
     *
     * @param dateDate
     * @return
     */
    public static String dateToStrLong(java.util.Date dateDate) {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String dateString = formatter.format(dateDate);
        return dateString;
    }

    public static long stringTotime(String dateDate) {
        long time = 0L;
        try {
//            String dateTime = "2016-12-31 12:30:45";
            java.util.Calendar calendar = java.util.Calendar.getInstance();
            calendar.setTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").parse(dateDate));
            time = calendar.getTimeInMillis();
            log.debug("日期[{}]对应的毫秒数：{}", dateDate, calendar.getTimeInMillis());
        } catch (ParseException pe) {

        }
        return time;
    }

    /**
     * 毫秒转换成时分秒
     *
     * @param mss
     * @return
     */
    public static String formatDuring(long mss) {
        /*long days = mss / (1000 * 60 * 60 * 24);*/
        long hours = mss / (1000 * 60 * 60);
        long minutes = (mss % (1000 * 60 * 60)) / (1000 * 60);
        long seconds = (mss % (1000 * 60)) / 1000;
        /*return hours + " 小时 " + minutes + " 分 " + seconds + " 秒 ";*/
        return hours + " 小时 " + minutes + " 分 ";
    }

    /**
     * 毫秒转换成时分秒
     *
     * @param mss
     * @return
     */
    public static String formatDuring2(long mss) {
        //long days = mss / (1000 * 60 * 60 * 24);
        long hours = mss / (1000 * 60 * 60);
        long minutes = (mss % (1000 * 60 * 60)) / (1000 * 60);
        long seconds = (mss % (1000 * 60)) / 1000;
        return hours + " 小时 " + minutes + " 分 " + seconds + " 秒 ";
    }

    /**
     * 转换成日期
     *
     * @param date
     * @return
     */
    public static String dateToShortStr(String date) {
        if (date != null) {
            String[] var1 = date.split(" ");
            int two = 2;
            if (var1.length >= two) {
                return var1[0];
            } else if (var1.length == 1) {
                return var1[0];
            } else {
                return date;
            }
        }
        return null;
    }

    /**
     * 判断当前时间是否在[startTime, endTime]区间，注意时间格式要一致 "HH:mm:ss"
     *
     * @param sNowTime   当前时间
     * @param sStartTime 开始时间
     * @param sSendTime  结束时间
     * @return
     * @author jacky.liu
     */
    public static boolean isEffectiveDate(String sNowTime, String sStartTime, String sSendTime) {
        try {
            String format = "HH:mm:ss";
            Date nowTime = new SimpleDateFormat(format).parse(sNowTime);
            Date startTime = new SimpleDateFormat(format).parse(sStartTime);
            Date endTime = new SimpleDateFormat(format).parse(sSendTime);

            if (nowTime.getTime() == startTime.getTime()
                    || nowTime.getTime() == endTime.getTime()) {
                return true;
            }

            java.util.Calendar date = java.util.Calendar.getInstance();
            date.setTime(nowTime);

            java.util.Calendar begin = java.util.Calendar.getInstance();
            begin.setTime(startTime);

            java.util.Calendar end = java.util.Calendar.getInstance();
            end.setTime(endTime);

            if (date.after(begin) && date.before(end)) {
                return true;
            } else {
                return false;
            }
        } catch (ParseException pe) {
            return false;
        }
    }

    /**
     * 比较大小，注意时间格式要一致 "HH:mm:ss"
     *
     * @param sNowTime   当前时间
     * @param sStartTime 开始时间
     * @param sSendTime  结束时间
     * @return
     * @author jacky.liu
     */
    public static boolean isDateAfter(String sNowTime, String sStartTime, String sSendTime) {
        try {
            String format = "HH:mm:ss";
            Date nowTime = new SimpleDateFormat(format).parse(sNowTime);
            Date startTime = new SimpleDateFormat(format).parse(sStartTime);
            Date endTime = new SimpleDateFormat(format).parse(sSendTime);

            if (nowTime.getTime() == startTime.getTime()
                    || nowTime.getTime() == endTime.getTime()) {
                return true;
            }

            java.util.Calendar date = java.util.Calendar.getInstance();
            date.setTime(nowTime);

            java.util.Calendar begin = java.util.Calendar.getInstance();
            begin.setTime(startTime);

            java.util.Calendar end = java.util.Calendar.getInstance();
            end.setTime(endTime);

            if (date.after(begin) && date.before(end)) {
                return true;
            } else {
                return false;
            }
        } catch (ParseException pe) {
            return false;
        }
    }

    /**
     * 将时间转换成yyyy-MM-dd hh:mm:ss 格式
     * <p>如果@param date 为null的话，将使用系统当前时间转换</p>
     *
     * @param date
     * @return
     */
    public static String dateToString(Date date) {
        return dateToStrLong(date == null ? new Date() : date);
    }

    public static String dateToShortString(Date date) {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        String dateString = formatter.format(date);
        return dateString;
    }

    /**
     * 构造时间
     *
     * @param date
     * @param time
     * @return
     */
    public static Date structDate(Date date, String time) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            return sdf.parse(dateToShortString(date) + " " + time + ":00");
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 将毫秒转换成小时
     *
     * @param timeStamp
     * @return
     */
    public static float toHour(long timeStamp) {
        if (timeStamp == 0) {
            return 0;
        }
        float var1 = (float) timeStamp;
        float h = 1000 * 60 * 60;
        return var1 / (h);
    }

    public static float toHour(long timeStamp, int digit) {
        return Float.valueOf(String.valueOf(NumberFormatUtil.round(toHour(timeStamp), digit)));
    }

    /**
     * 作者：damei2017
     * 来源：CSDN
     * 原文：https://blog.csdn.net/damei2017/article/details/86468852
     * 版权声明：本文为博主原创文章，转载请附上博文链接！
     */
    public static String timeStampToDate(Long stamp, String format) {
        if (format == null || format.isEmpty()) {
            format = "yyyy-MM-dd HH:mm:ss";
        }
        SimpleDateFormat sdf = new SimpleDateFormat(format);
        return sdf.format(new Date(stamp));
    }

    public static String timeStampToDate(Long stamp) {
        return timeStampToDate(stamp, null);
    }

    /**
     * 将时间转换成日期
     *
     * @param date
     * @return
     */
    public static Date conventToShortDate(Date date) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String format = simpleDateFormat.format(date);
        try {
            SimpleDateFormat targetSdf = new SimpleDateFormat("yyyy-MM-dd");
            return targetSdf.parse(format);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * @param startTime
     * @param endTime
     * @return
     */
    public static List<String> getDays(String startTime, String endTime) {

        // 返回的日期集合
        List<String> days = new ArrayList<>();

        DateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
        try {
            Date start = dateFormat.parse(startTime);
            Date end = dateFormat.parse(endTime);

            java.util.Calendar tempStart = java.util.Calendar.getInstance();
            tempStart.setTime(start);

            java.util.Calendar tempEnd = java.util.Calendar.getInstance();
            tempEnd.setTime(end);
            /*Date plus 1 (including end)*/
            tempEnd.add(java.util.Calendar.DATE, +1);
            while (tempStart.before(tempEnd)) {
                days.add(dateFormat.format(tempStart.getTime()));
                tempStart.add(java.util.Calendar.DAY_OF_YEAR, 1);
            }

        } catch (ParseException e) {
            e.printStackTrace();
        }

        return days;
    }

    public static List<String> getDays(Date startTime, Date endTime) {
        return getDays(dateToString(startTime), dateToString(endTime));
    }

    /**
     * 时间字符串转成时间对象
     *
     * @param s
     * @return
     */
    public static Date stringToDate(String s) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
        try {
            return simpleDateFormat.parse(s);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * @param start1
     * @param end1
     * @param start2
     * @param end2
     * @return
     */
    public static long countDateIntersection(Date start1, Date end1, Date start2, Date end2) {
        SimpleDateFormat sdf2 = new SimpleDateFormat("HH:mm:ss");
        long s1 = 0;
        long s2 = 0;
        long e1 = 0;
        long e2 = 0;
        try {
            //标准化到1970-01-01
            s1 = sdf2.parse(sdf2.format(start1)).getTime();
            s2 = sdf2.parse(sdf2.format(start2)).getTime();
            e1 = sdf2.parse(sdf2.format(end1)).getTime();
            e2 = sdf2.parse(sdf2.format(end2)).getTime();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        if (!(s2 > e1 || s1 > e2)) {
            long s = s1 > s2 ? s1 : s2;
            long e = e1 < e2 ? e1 : e2;
            return e - s;
        }
        return 0;
    }

    public static long countDateIntersection(Long start1, Long end1, Long start2, Long end2) {
        long s1 = start1;
        long s2 = start2;
        long e1 = end1;
        long e2 = end2;
        if (!(s2 > e1 || s1 > e2)) {
            long s = s1 > s2 ? s1 : s2;
            long e = e1 < e2 ? e1 : e2;
            return e - s;
        }
        return 0;
    }

    /**
     * 转换时间字符串，如：08:16
     *
     * @param time
     * @return
     * @Deprecated
     */
    public static Long parseTime(String time) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm");
        try {
            return simpleDateFormat.parse(time).getTime();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return 0L;
    }

    public static Long parseSkillfulTime(String time) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm:ss");
        try {
            return simpleDateFormat.parse(time).getTime();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return 0L;
    }

    public static final String SHORT_FORMAT = "HH:mm:ss";

    public static Long parseStamp(String point, String format) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd " + format);
        String d = "2019-07-16";
        try {
            Date date = simpleDateFormat.parse(d + " " + point);
            Date day = stringToDate(d);
            return date.getTime() - day.getTime();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 将时间字符转换成时间戳
     *
     * @param str
     * @return
     */
    public static Long parseStrToStamp(String str) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        try {
            return sdf.parse(str).getTime();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static Long subDateToShortStamp(Date date) {
        return parseStrToStamp(DateUtil.splitTime(date));
    }

    public static class DateConstant {
        /**
         * 天数加减
         *
         * @param date
         * @param num
         * @return
         */
        public static Date addDay(Date date, int num) {
            java.util.Calendar c = java.util.Calendar.getInstance();
            c.setTime(date);
            c.add(java.util.Calendar.DAY_OF_MONTH, num);
            return c.getTime();
        }

        public static String addDayByString(String date, int num) {
            Date var = addDay(DateUtil.stringToDate(date), num);
            return DateUtil.dateToShortString(var);
        }

        public static String today() {
            return DateUtil.dateToShortDate(new Date());
        }

        public static Date currentDate() {
            return new Date();
        }

        /**
         * 判断时间是为空，如果为空将返回当前时间
         *
         * @param source
         * @return
         */
        public static Date getDate(Date source) {
            return source == null ? new Date() : source;
        }

        /**
         * 获取某年某月的第一天
         *
         * @throws
         * @Title:getFisrtDayOfMonth
         * @Description:
         * @param:@param year
         * @param:@param month
         * @param:@return
         * @return:String
         */
        public static String getFirstDayOfMonth(int year, int month) {
            java.util.Calendar cal = java.util.Calendar.getInstance();
            //设置年份
            cal.set(java.util.Calendar.YEAR, year);
            //设置月份
            cal.set(java.util.Calendar.MONTH, month - 1);
            //获取某月最小天数
            int firstDay = cal.getActualMinimum(java.util.Calendar.DAY_OF_MONTH);
            //设置日历中月份的最小天数
            cal.set(java.util.Calendar.DAY_OF_MONTH, firstDay);
            //格式化日期
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            String firstDayOfMonth = sdf.format(cal.getTime());
            return firstDayOfMonth;
        }

        /**
         * 获取某年某月的第一天
         *
         * @param d 一个日期或日期时间
         * @return
         */
        public static String getFirstDayOfMonth(String d) {
            Date date = DateUtil.stringToDate(d);
            return getFirstDayOfMonth(date);
        }

        public static String getFirstDayOfMonth(Date date) {
            java.util.Calendar calendar = Calendar.getInstance(date);
            int y = calendar.get(java.util.Calendar.YEAR);
            int m = calendar.get(java.util.Calendar.MONTH);
            return getFirstDayOfMonth(y, m + 1);
        }

        public static String now() {
            return DateUtil.dateToString(new Date());
        }

        public static final Long HOUR = 1000 * 60 * 60L;
        public static final Long DAY = HOUR * 24;

        /**
         * 获取两个日期之间的天数
         *
         * @param var1
         * @param var2
         * @return
         */
        public static int getDayCount(String var1, String var2) {
            Long stamp1 = DateUtil.stringToDate(var1).getTime();
            Long stamp2 = DateUtil.stringToDate(var2).getTime();

            return ((stamp2.intValue() - stamp1.intValue()) / DAY.intValue());
        }

        public static void main(String[] args) {
            /* DateUtil.parseTime("12:00") => 14400000*/
            System.out.println(DateUtil.timeStampToDate(14400000L, "HH:mm"));
        }
    }

    static class Calendar {
        public static java.util.Calendar getInstance(String d) {
            Date date = DateUtil.stringToDate(d);
            return getInstance(date);
        }

        public static java.util.Calendar getInstance(Date date) {
            java.util.Calendar calendar = java.util.Calendar.getInstance();
            calendar.setTime(date);
            return calendar;
        }
    }
}
